package de.playmee;

import de.playmee.dialogs.CustomDialog;
import de.playmee.dialogs.EditChannelDialog;
import de.playmee.dialogs.ProgressWheelDialog;
import de.playmee.handler.AccountHandler;
import de.playmee.handler.ChannelHandler;
import de.playmee.handler.ChannelTrackRatingHandler;
import de.playmee.handler.MusicHandler;
import de.playmee.handler.PlaylistHandler;
import de.playmee.services.LoadingService.DownloadTrackDataListener;
import de.playmee.services.MusicService;
import de.playmee.tasks.ComputePlaylistTask;
import de.playmee.tasks.ComputePlaylistTask.PlaylistComputedListener;
import de.playmee.views.SimpleChannelViewAdapter;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class ChannelActivity extends MainMenuActivity implements PlaylistComputedListener {

	private final String TAG = "ChannelActivity";
	private final int IMAGE_SIZE = 70; // dp
	
	private Playmee application;
	
	private ProgressWheelDialog progressWheelDialog;
	
	private ChannelHandler cHandler;
	private AccountHandler aHandler;
	private PlaylistHandler pHandler;
	private ChannelTrackRatingHandler ctrHandler;
	private TextView header;
	private GridView gridView;
	private Handler initHandler;
	
	private boolean tracksDataDownloaded;
	
	/**
	 * called when the activity is first created
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.channel);
		
		application = (Playmee) getApplication();
		
		progressWheelDialog = new ProgressWheelDialog(this);
		
		cHandler = application.getChannelHandler();
		aHandler = application.getAccountHandler();
		pHandler = application.getPlaylistHandler();
		ctrHandler = application.getChannelTrackRatingHandler();
		header = (TextView) findViewById(R.id.rating_header);
		gridView = (GridView) findViewById(R.id.channel_gridview);
		
		// show dialog with all actions
		gridView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
				Channel channel = cHandler.loadChannel(id);
				showActionsDialog(channel);
			}
		});
		
		initHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				refreshView();
			}
		};
		
		MusicHandler mHandler = application.getMusicHandler();
		tracksDataDownloaded = mHandler.getCheckCount() == 0;
		application.addDownloadTrackDataListener(new DownloadTrackDataListener() {	
			@Override
			public void onSingleTrackDataDownloaded(Track track) {
				// nothing to do
			}
			
			@Override
			public void onAllTracksDataDownloaded() {
				tracksDataDownloaded = true;
			}
		});
		
		refreshView();
	}
	
	/**
	 * called when the options menu is first created
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.channel, menu);
		return super.onCreateOptionsMenu(menu);
    }
	
	/**
	 * called once the menu is selected
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		// decide which menu option is selected
		case R.id.add:
			// create new channel and open edit dialog
			Channel channel = new Channel("New channel");
			new EditChannelDialog(ChannelActivity.this, cHandler, channel, ctrHandler,
					initHandler, application.dpToPx(IMAGE_SIZE)).show();
			break;
		default:
			return super.onOptionsItemSelected(item);
		}
		return true;
    }
	
	/**
	 * shows a dialog with all actions for a channel
	 * 
	 * @param position
	 */
	private void showActionsDialog(final Channel channel) {
		final String PLAY = "Play";
		final String NOPLAY = "Busy downloading\nPlease wait...";
		final String DETAILS = "Show details";
		final String EDIT = "Edit Attributes";
		final String DELETE = "Delete";
		
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setIcon(android.R.drawable.ic_menu_manage);
		builder.setTitle(channel.getLabel());
		// final String[] actionsPlay = { PLAY, DETAILS, EDIT, DELETE };
		// final String[] actionsNoPlay = { NOPLAY, DETAILS, EDIT, DELETE };
		final String[] actionsPlay = { PLAY, EDIT, DELETE };
		final String[] actionsNoPlay = { NOPLAY, EDIT, DELETE };
		
		final String[] actions;
		if (tracksDataDownloaded) {
			actions = actionsPlay;
		} else {
			actions = actionsNoPlay;
		}
		
		builder.setItems(actions, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int item) {
		    	CharSequence action = actions[item];
		    	
		    	// play
		    	if (action.equals(PLAY)) {
		    		playChannel(channel);
		    	}
		    	// details
		    	else if (action.equals(DETAILS)) {
		    		CustomDialog.showInfoDialog(ChannelActivity.this, "Details",
		    				channel.getInfo());
		    	}
		    	// edit
		    	else if (action.equals(EDIT)) {
					new EditChannelDialog(ChannelActivity.this, cHandler, channel, ctrHandler,
							initHandler, application.dpToPx(IMAGE_SIZE)).show();
		    	}
		    	// delete
		    	else if (action.equals(DELETE)) {
		    		showDeleteDialog(channel);
		    	}
		    }
		});
		
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	/**
	 * shows a dialog to delete the channel
	 * 
	 * @param channel
	 */
	private void showDeleteDialog(final Channel channel) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setIcon(android.R.drawable.ic_menu_delete);
		builder.setTitle("Delete " + channel.getLabel());
		builder.setMessage("Are you sure you want to delete this channel?");
		builder.setCancelable(false); // user cannot close dialog with back button
		setCancelButton(builder, "No"); // button to cancel deleting
		
		// button to delete channel
		builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				boolean removed = cHandler.deleteChannel(channel.getId());
				if (removed) {
					pHandler.deletePlaylist(channel.getId());
					refreshView();
				} else {
					CustomDialog.showAlertDialog(ChannelActivity.this, "Error",
							"The channel could not be deleted. Please try again.");
				}
			}
		});
		
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	/**
	 * sets a cancel button for the given builder
	 * 
	 * @param builder
	 * @param text
	 */
	private void setCancelButton(AlertDialog.Builder builder, CharSequence text) {
		builder.setNegativeButton(text, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
			}
		});
	}
	
	/**
	 * refreshes the View (needed if underlying data has been changed)
	 */
	private void refreshView() {
		int count = cHandler.getCount(ChannelHandler.DATABASE_TABLE, null);
		
		// no channels available
		if (count == 0) {
			// update header and hide grid view
			Log.i(TAG, "No channels available.");
			header.setText(R.string.channel_nothing);
			gridView.setVisibility(GridView.GONE);
		}
		
		// at least 1 channel available
		else {
			// update header and show grid view
			String headerText = count + " channel" + (count == 1 ? "" : "s") + " available.";
			Log.i(TAG, headerText);
			header.setText(headerText);
			gridView.setVisibility(GridView.VISIBLE);
			
			Log.i(TAG, "Creating view to display channels...");
			
			// create new adapter
			SimpleChannelViewAdapter adapter = new SimpleChannelViewAdapter(this, cHandler,
					ChannelHandler.ORDER_BY_LABEL_ABC, application.dpToPx(70));
			gridView.setAdapter(adapter);
			
			Log.i(TAG, "Done creating view. Channels are displayed.");
		}
	}
	
	/**
	 * computes the playlist and starts playing
	 * 
	 * @param channel
	 */
	private void playChannel(Channel channel) {
		progressWheelDialog.show();
		
		boolean gpsEnabled = application.gpsLocationProviderIsEnabled()
				|| application.networkLocationProviderIsEnabled();
		Weather weather = application.getWeather();
		
		// if the current weather conditions should be considered
		// make sure that they were loaded before
		if (channel.isConsideringWeather()) {
			if (!gpsEnabled || weather.getCurrentWeather() == null) {
				progressWheelDialog.dismiss();
				CustomDialog.showInfoDialog(ChannelActivity.this, "Playing failed.",
						"Cannot consider the current weather conditions.\n" +
						"Please enable localisation via GPS/WiFi or disable " +
						"this channel attribute.");
				return;
			}
		}
		
		// check if we are connected to the internet
		boolean hasNetworkConnetion = application.hasNetworkConnection();
		
		// if the current weather conditions should be considered
		// make sure that we have an internet connection
		if (channel.isConsideringWeather() && !hasNetworkConnetion) {
			progressWheelDialog.dismiss();
			CustomDialog.showInfoDialog(ChannelActivity.this, "Playing failed.",
					"Cannot consider the current weather conditions.\n" +
					"Please check your internet connection or disable " +
					"this channel attribute.");
			return;
		}
		
		// start computing the playlist
		(new ComputePlaylistTask(aHandler, pHandler, channel, hasNetworkConnetion,
				weather, this)).execute();
	}
	
	@Override
	public void onPlaylistComputed(Playlist playlist) {
		if (playlist == null) {
			// nothing can be played
			CustomDialog.showInfoDialog(ChannelActivity.this, "Playing failed",
					"Cannot create a playlist for this channel. " +
					"Please check your internet connection and try again.");
			progressWheelDialog.dismiss();
			return;
		}
		
		pHandler.setCurrentPlaylist(playlist);
		progressWheelDialog.dismiss();
		
		// start playing and switch to the player tab
		startService(new Intent(MusicService.ACTION_STOP));
		startService(new Intent(MusicService.ACTION_PLAY)); // TODO
		MainActivity mainActivity = (MainActivity) getParent();
		mainActivity.switchTab(mainActivity.TAB_PLAYER);
	}
}
